package vn.edu.hut.soict.translate.dictionary.bilingual;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class BilingualDictionaryWithPOSReader {
	private static final char WORD_SIGN = '@';
	private static final char POS_SIGN = '*';
	private static final char MEANING_SIGN = '-';
	private static final char EXAMPLE_SIGN = '=';

	private static final String UNKNOWN_STRING = "unknown";
	private static final String N = "danh từ";
	private static final String V = "động từ";
	private static final String A = "tính từ";
	private static final String P = "đại từ";
	private static final String M = "số từ";
	private static final String R = "phó từ";
	private static final String C = "liên từ";
	private static final String E = "giới từ";
	private static final String I = "từ cảm thán";

	private static final String POS_SEPARATOR = ",";
	private static final String MEANING_SEPARATOR = ";";

	private BilingualDictionaryWithPOS dictionary;
	private int lineNumber;
	private String currentLine;

	private String word;
	private List<PartOfSpeech> posList;

	public BilingualDictionaryWithPOSReader() {

	}

	public BilingualDictionaryWithPOS read(String file) {
		dictionary = new BilingualDictionaryWithPOS();
		BufferedReader reader = null;
		lineNumber = 0;
		try {
			reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
			while ((currentLine = reader.readLine()) != null) {
				lineNumber++;
				try {
					parse();
				}
				catch (Exception e) {
					// TODO Auto-generated catch block
					// e.printStackTrace();
					System.err.println(e.getMessage());
				}
			}
		}
		catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally {
			try {
				if (reader != null) {
					reader.close();
				}
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}

		return dictionary;
	}

	private String removeComment(String content) {
		while (true) {
			int first = content.indexOf('(');
			if (first < 0) {
				break;
			}
			int last = content.indexOf(')');
			if (last >= 0) {
				content = content.substring(0, first) + content.substring(last + 1, content.length());
			}
		}
		return content.trim();
	}

	private void parse() throws Exception {
		if (currentLine.isEmpty()) {
			return;
		}
		switch (currentLine.charAt(0)) {
			case WORD_SIGN:
				parseWord();
				break;
			case POS_SIGN:
				parsePOSList();
				break;
			case MEANING_SIGN:
				parseMeaningList();
				break;
			case EXAMPLE_SIGN:
				parseExample();
				break;
			default:
				throw new Exception("Parse bilingual dictionary error at line " + lineNumber);
		}
	}

	private void parseWord() {
		word = currentLine.substring(1).trim();
		posList = null;
	}

	private void parsePOSList() throws Exception {
		posList = new ArrayList<PartOfSpeech>();
		String[] posArray = removeComment(currentLine.substring(1)).split(POS_SEPARATOR);

		for (String posString : posArray) {
			posString = posString.trim();
			PartOfSpeech pos = null;

			if (posString.equalsIgnoreCase(UNKNOWN_STRING)) {
				pos = PartOfSpeech.UNKNOWN;
			}
			else if (posString.equalsIgnoreCase(N)) {
				pos = PartOfSpeech.N;
			}
			else if (posString.equalsIgnoreCase(P)) {
				pos = PartOfSpeech.P;
			}
			else if (posString.equalsIgnoreCase(V)) {
				pos = PartOfSpeech.V;
			}
			else if (posString.equalsIgnoreCase(A)) {
				pos = PartOfSpeech.A;
			}
			else if (posString.equalsIgnoreCase(M)) {
				pos = PartOfSpeech.M;
			}
			else if (posString.equalsIgnoreCase(R)) {
				pos = PartOfSpeech.R;
			}
			else if (posString.equalsIgnoreCase(C)) {
				pos = PartOfSpeech.C;
			}
			else if (posString.equalsIgnoreCase(E)) {
				pos = PartOfSpeech.E;
			}
			else if (posString.equalsIgnoreCase(I)) {
				pos = PartOfSpeech.I;
			}
			else {
				throw new Exception("Parse bilingual dictionary error at line " + lineNumber);
			}

			posList.add(pos);
		}
	}

	private void parseMeaningList() {
		String[] meaningArray = removeComment(currentLine.substring(1)).split(MEANING_SEPARATOR);
		for (String meaning : meaningArray) {
			for (PartOfSpeech pos : posList) {
				meaning = meaning.trim().toLowerCase();
				dictionary.addEntry(word, new SimpleDictionaryEntry(meaning, pos));
			}
		}
	}

	private void parseExample() {
		// Do nothing
	}
}